﻿using AIVision.Inspect.Halcon;
using AIVision.Model;
using AIVision.Model.EntityModels;
using AIVision.Model.Events;
using AIVision.Model.InspectModels;
using AIVision.Model.MachineModels;
using AIVision.Model.UIModels;
using AIVision.Repository.Services;
using HalconDotNet;
using Microsoft.Extensions.Configuration;
using Prism.Events;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Effects;
using System.Windows.Threading;

namespace AIVision.Inspect
{
    public class CheckTempleteAgent
    {
        private readonly IContainerProvider containerProvider;
        private readonly InspectStatusModel inspectStatus;
        private readonly MachineStatusModel machineStatus;
        private readonly SummaryDataModel viewDataModel;
        private readonly CheckTempleteService checkTempleteService;
        private readonly IEventAggregator eventAggregator;

        CheckTemplateDto checkTemplateCfg;
        Task mainTask;
        ObservableCollection<CheckStationAgent> checkStations;
        bool IsInitOK=false;
        bool MoveFlag = false;
        string DatePathName = DateTime.Now.ToString("yyyy-MM-dd");
        public CheckTempleteAgent(IContainerProvider containerProvider,InspectStatusModel inspectStatus,MachineStatusModel machineStatus,SummaryDataModel viewDataModel, CheckTempleteService checkTempleteService, IEventAggregator eventAggregator)
        {
            this.eventAggregator = eventAggregator;
            this.containerProvider = containerProvider;
            this.inspectStatus = inspectStatus;
            this.machineStatus = machineStatus;
            this.viewDataModel = viewDataModel;
            this.checkTempleteService = checkTempleteService;
        }
        public void Init()
        {
            if (IsInitOK)
                return;
            try
            {
                checkTemplateCfg = checkTempleteService.GetStartTemplete();

                //1、初始化VisionStation
                checkStations = new ObservableCollection<CheckStationAgent>();
                foreach (var stationCfg in checkTemplateCfg.CheckStations)
                {
                    CheckStationAgent checkStation = containerProvider.Resolve<CheckStationAgent>();
                    checkStation.Init(stationCfg);
                    checkStations.Add(checkStation);
                }
                //2、初始化SampleQueue
                int firstposition = machineStatus.ZhuanTaiStatus.Location;
                var stationCount = checkStations.GroupBy(m => m.CheckStationCfg.Index).Count();
                for (int i = 0; i < stationCount; i++)
                {
                    int pos =DevicePositionSub(firstposition, stationCount-i+1,8); //DevicePositionHelper.Sub(firstposition, checkStations.Count - 1 - i, appServiceContext.Machine.PositionRadix);

                    SampleDataModel emptySample = new SampleDataModel()
                    {
                        Code = "Empty_" + pos.ToString() + "_" + i.ToString(),
                        InspectUnitResults = new Dictionary<int, InspectResultModel>(),
                        Location = pos
                    };
                    Dictionary<string, HObject> defect = new Dictionary<string, HObject>();
                    HObject htemp;
                    HOperatorSet.GenEmptyRegion(out htemp);
                    defect.Add("初始不良", htemp);
                    emptySample.InspectUnitResults.Add(i, new InspectResultModel() { Score = 0, Defects = defect });

                    inspectStatus.SampleDataList.Insert(inspectStatus.SampleDataList.Count, emptySample);
                }
                //3、初始化图片输出目录
                foreach (var station in checkStations)
                {
                    if (station.CheckStationCfg.IsSaveOKImage)
                    {
                        if (!Directory.Exists(Path.Combine(station.CheckStationCfg.ImageFileSavePath, DatePathName)))
                        {
                            Directory.CreateDirectory(Path.Combine(station.CheckStationCfg.ImageFileSavePath, DatePathName));
                        }
                    }
                    if (station.CheckStationCfg.IsSaveDefectImage)
                    {
                        if (!Directory.Exists(Path.Combine(station.CheckStationCfg.ImageFileSavePath, DatePathName)))
                        {
                            Directory.CreateDirectory(Path.Combine(station.CheckStationCfg.ImageFileSavePath, DatePathName));
                        }
                    }
                }
                //4、启动主任务线程
                mainTask = new Task(MainTask);
                mainTask.Start();

                eventAggregator.GetEvent<InspectRunMsgEvent>().Publish(new RunMsgModel($"初始化完成!", "Green"));
                IsInitOK = true;
            }
            catch (Exception ex)
            {
                eventAggregator.GetEvent<InspectRunMsgEvent>().Publish(new RunMsgModel($"初始失败{ex.Message}!", "Red"));
                return;
            }
        }

        private void MainTask()
        {
            while (true) { 
                if(inspectStatus.VisionPhotoReady)
                {
                    inspectStatus.VisionPhotoReady = false;
                    //Trace.WriteLine(Thread.CurrentThread.ManagedThreadId+":出发拍照");
                    //0、确认位置正确
                    if (inspectStatus.SampleDataList[0].Location == machineStatus.ZhuanTaiStatus.Location)
                    {
                        var newSampleData = new SampleDataModel()
                        {
                            Code = Guid.NewGuid() + "_" + machineStatus.ZhuanTaiStatus.Location.ToString(),
                            InspectUnitResults = new Dictionary<int, InspectResultModel>(),
                            StartLocation = machineStatus.ZhuanTaiStatus.Location,
                            Location = machineStatus.ZhuanTaiStatus.Location
                        };

                        inspectStatus.SampleDataList.Insert(inspectStatus.SampleDataList.Count, newSampleData);
                        //RunRecord.CheckQty += 1;
                        // 移位触发，列队末移除一个产品
                        inspectStatus.SampleDataList.Remove(inspectStatus.SampleDataList[0]);
                    }
                    else
                    {
                        viewDataModel.LocationErrQty += 1;
                        inspectStatus.SampleDataList.Clear();
                        //2、初始化SampleQueue
                        int firstposition = machineStatus.ZhuanTaiStatus.Location;
                        var stationCount = checkStations.GroupBy(m => m.CheckStationCfg.Index).Count();
                        for (int i = 0; i < stationCount; i++)
                        {
                            int pos = DevicePositionSub(firstposition, stationCount - i-1, 8); //DevicePositionHelper.Sub(firstposition, checkStations.Count - 1 - i, appServiceContext.Machine.PositionRadix);

                            SampleDataModel emptySample = new SampleDataModel()
                            {
                                Code = "Empty_" + pos.ToString() + "_" + i.ToString(),
                                InspectUnitResults = new Dictionary<int, InspectResultModel>(),
                                Location = pos
                            };
                            Dictionary<string, HObject> defect = new Dictionary<string, HObject>();
                            HObject htemp;
                            HOperatorSet.GenEmptyRegion(out htemp);
                            defect.Add("错位不良", htemp);
                            emptySample.InspectUnitResults.Add(i, new InspectResultModel() { Score = 0, Defects = defect });

                            inspectStatus.SampleDataList.Insert(inspectStatus.SampleDataList.Count, emptySample);
                        }
                    }
                    //1、多线程执行拍摄，等待拍摄完成结果，将图像信息存入工位。
                    GetStationImage();
                    viewDataModel.ZhiXingPaiZhaoQty += 1;
                    //2、反馈拍摄完成信号

                    inspectStatus.VisionPhotoComplete = true;


                    //Trace.WriteLine(Thread.CurrentThread.ManagedThreadId + ":拍照完成");
                    //3、执行检查，将结果写入SampleQueue，列队未进行移位
                    ExStationInspect();
                    //4、位置校对，判断是移位触发还是软触发 移位后列队增加新样品
                    //列队移位-需要等到检查完成后在进行移位，设备已经进行转动，列队移位后结果和实际对齐。
                    //var queueFirstSample = inspectStatus.SampleDataList[inspectStatus.SampleDataList.Count - 1];
                    //if (queueFirstSample.Location == DevicePositionSub(machineStatus.ZhuanTaiStatus.Location,1,8))
                    //    MoveFlag = true;
                    //else
                    //    MoveFlag = false;
                    //if (MoveFlag)  //移位触发，列队追加产品
                    //{
                    //    int prison = queueFirstSample.Location + 1;
                    //    if (prison > 8)
                    //        prison = 1;

                    //    var newSampleData = new SampleDataModel()
                    //    {
                    //        Code = Guid.NewGuid() + "_" + prison.ToString(),
                    //        InspectUnitResults = new Dictionary<int, InspectResultModel>(),
                    //        Location = prison
                    //    };

                    //    inspectStatus.SampleDataList.Insert(inspectStatus.SampleDataList.Count, newSampleData);
                    //    //RunRecord.CheckQty += 1;
                    //    // 移位触发，列队末移除一个产品
                    //    inspectStatus.SampleDataList.Remove(inspectStatus.SampleDataList[0]);

                    //}
                    //else
                    //    viewDataModel.LocationErrQty += 1;


                   
                    //5、计算queue中的结果，列队位移后。

                    CalcSampleOut();
                    //6、输出检查完成信号，复位拍照就绪信号
                    inspectStatus.VisionInspectComplete = true;
                    //Trace.WriteLine(Thread.CurrentThread.ManagedThreadId + ":检查完成");
                   

                }
                else if(inspectStatus.ManualPhotoReady)
                {
                    inspectStatus.ManualPhotoReady = false;
                    GetStationImage();
                    ExStationInspect();
                    CalcSampleOut();
                }
            }
        }
        private void GetStationImage()
        {
            List<Task> tasks = new List<Task>();
            foreach (var cameraStation in checkStations.Where(m=>m.CheckStationCfg.StationType==EnumStationType.Camera.ToString()).ToList() )
            {
                Task task = Task.Factory.StartNew(() =>
                {
                    Task.Delay(cameraStation.CheckStationCfg.PhotoDelay).Wait();
                    cameraStation.GetImage();
                });
                tasks.Add(task);
            }
            Task.WaitAll(tasks.ToArray());
        }
        private void ExStationInspect()
        {
            //执行检查
            List<Task> tasks = new List<Task>();
            foreach (var station in checkStations.Where(m => m.CheckStationCfg.StationType == EnumStationType.Camera.ToString() && !string.IsNullOrEmpty(m.CheckStationCfg.InspectType) ).ToList())
            {
                Task task = Task.Run(() =>
                {
                    //SampleDataModel currentSample = SampleQueue.ElementAt(station.CheckStationCfg.Index);
                    SampleDataModel currentSample = inspectStatus.SampleDataList[station.CheckStationCfg.Index];
                    station.ExInspect(currentSample);
                    if (station.FinalCheckUnitResult != null)
                    {
                        //检测结果写入列队
                        if (currentSample.InspectUnitResults.ContainsKey(station.CheckStationCfg.Index))
                            currentSample.InspectUnitResults.Remove(station.CheckStationCfg.Index);
                        currentSample.InspectUnitResults.Add(station.CheckStationCfg.Index, station.FinalCheckUnitResult);
                    };
                });
                 tasks.Add(task);
            }
            Task.WaitAll(tasks.ToArray());
        }

        private void CalcSampleOut()
        {
            //计算结果
            var outOKStation = checkStations.FirstOrDefault(m => m.CheckStationCfg.StationType == EnumStationType.OutOK.ToString());
            if (outOKStation == null)
            {
                throw new Exception("OK下料工位错误!");
            }
            SampleDataModel outSampleData = inspectStatus.SampleDataList[outOKStation.CheckStationCfg.Index+1];
            viewDataModel.OutCode = outSampleData.Location.ToString();
            if (outSampleData.ScoreTotal >= outOKStation.CheckStationCfg.OutScore)
            {
                inspectStatus.OKLiao = true;
                viewDataModel.OkQty += 1;
            }
            else
            {
                inspectStatus.OKLiao = false;
                viewDataModel.NgQty += 1;

                foreach (var ir in outSampleData.InspectUnitResults)
                {
                    if (ir.Value.OKScore != ir.Value.Score)
                    {
                        if (ir.Value.InspectType == EnumInspectType.OBJ.ToString())
                        {
                            if (!viewDataModel.DefectCount.ContainsKey("缺件"))
                                viewDataModel.DefectCount.Add("缺件", 1);
                            else
                                viewDataModel.DefectCount["缺件"] += 1;
                        }
                        else
                        {
                            foreach (var defect in ir.Value.Defects)
                            {
                                if (!viewDataModel.DefectCount.ContainsKey(defect.Key))
                                    viewDataModel.DefectCount.Add(defect.Key, 1);
                                else
                                    viewDataModel.DefectCount[defect.Key] += 1;
                            }
                        }
                    }
                }



            }


            //建立存储路径
            string path = Path.Combine(outOKStation.CheckStationCfg.ImageFileSavePath, DatePathName, "SImages", outSampleData.Code);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            else
                viewDataModel.PathErrQty += 1;
            viewDataModel.PaiZhaoCalcQty += 1;     //拍照计算计数
            //保存 检测结果
            FileStream fs = new FileStream(path + "//" + outSampleData.Code + "result.txt", FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(string.Format("得分{0}", outSampleData.ScoreTotal));
            foreach (var v in outSampleData.InspectUnitResults)
            {
                if (outOKStation.CheckStationCfg.IsSaveOKImage)
                {
                    if (v.Value.InspectImage != null)
                    {
                        string fileName = Path.Combine(path, v.Key + "_" + outSampleData.Code + "_i.bmp");
                        try
                        {
                            HOperatorSet.WriteImage(v.Value.InspectImage, "bmp", 0, fileName);
                        }
                        catch (Exception ex)
                        {
                            viewDataModel.PhotoErrQty += 1;
                            //sw.WriteLine(string.Format("检测图Key为空"));
                        }
                    }
                }
                sw.WriteLine(string.Format("{0};{1};{2}", v.Key, v.Value.DefectNameSummary,outSampleData.Code));
                sw.WriteLine("---");
            }
            sw.WriteLine(string.Format("产品位置:{0},初始位置:{1}", outSampleData.Location,outSampleData.StartLocation));
            sw.WriteLine(string.Format("是否OK:{0}", inspectStatus.OKLiao));
            sw.Close();
            fs.Close();

            //存图
            //if (outOKStation.CheckStationCfg.IsSaveOKImage)
            //{
            //    foreach (var v in outSampleData.InspectUnitResults)
            //    {
            //        //if (v.Value.SourceImage != null)
            //        //{
            //        //    string fileName = Path.Combine(path, v.Key + "_" + outSampleData.Code + "_s.bmp");
            //        //    try
            //        //    {
            //        //        HOperatorSet.WriteImage(v.Value.SourceImage, "bmp", 0, fileName);
            //        //    }
            //        //    catch (Exception ex)
            //        //    {
            //        //        //sw.WriteLine(string.Format("原图Key为空"));
            //        //    }
            //        //}
                    

            //    }
            //}
        }



        private int DevicePositionAdd(int saddr, int step, int radix)
        {

            step = step % radix;

            if (saddr + step > radix)
            {
                return step - (radix - saddr);
            }
            else
                return saddr + step;

        }
        private int DevicePositionSub(int saddr, int step, int radix)
        {
            step = step % radix;
            if (saddr - step > 0)
            {
                return saddr - step;
            }
            else
                return saddr + radix - step;
        }

        private void CheckLocation()
        {
            var queueFirstSample = inspectStatus.SampleDataList[0];
            if (queueFirstSample.Location != DevicePositionAdd(machineStatus.ZhuanTaiStatus.Location, 1, 8))
            {

            }
        }
    }
}
